package net.zjitc.yaobei_backed.config;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;

/**
 * 兼容旧版 MD5 密码的 PasswordEncoder。
 * <p>
 * 优先使用 BCrypt 校验；如果存储的是 32 位 MD5 值，则退回到 MD5 校验。
 */
public class FlexiblePasswordEncoder implements PasswordEncoder {

    private final BCryptPasswordEncoder bcrypt = new BCryptPasswordEncoder();

    @Override
    public String encode(CharSequence rawPassword) {
        return bcrypt.encode(rawPassword);
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        if (encodedPassword == null || rawPassword == null) {
            System.out.println("PasswordEncoder: encodedPassword or rawPassword is null");
            return false;
        }

        System.out.println("PasswordEncoder: Checking password match");
        System.out.println("PasswordEncoder: encodedPassword = " + encodedPassword);
        System.out.println("PasswordEncoder: rawPassword = " + rawPassword.toString());

        if (isBcryptPassword(encodedPassword)) {
            System.out.println("PasswordEncoder: Detected BCrypt password");
            boolean result = bcrypt.matches(rawPassword, encodedPassword);
            System.out.println("PasswordEncoder: BCrypt matches result = " + result);
            return result;
        }

        if (isLegacyMd5Password(encodedPassword)) {
            System.out.println("PasswordEncoder: Detected MD5 password");
            String md5 = DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes(StandardCharsets.UTF_8));
            boolean result = encodedPassword.equalsIgnoreCase(md5);
            System.out.println("PasswordEncoder: MD5 matches result = " + result);
            return result;
        }

        System.out.println("PasswordEncoder: Password format not recognized");
        return false;
    }

    private boolean isBcryptPassword(String encodedPassword) {
        return encodedPassword.startsWith("$2a$")
                || encodedPassword.startsWith("$2b$")
                || encodedPassword.startsWith("$2y$");
    }

    private boolean isLegacyMd5Password(String encodedPassword) {
        return encodedPassword.length() == 32 && encodedPassword.matches("[0-9a-fA-F]{32}");
    }
}

